package com.chen.qhwhiteboardman.capture.whiteboard;

import android.opengl.GLES20;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

import com.chen.qhwhiteboardman.R;
import com.chen.qhwhiteboardman.capture.framework.gles.Drawable2dFull;
import com.chen.qhwhiteboardman.capture.framework.gles.core.Drawable2d;
import com.chen.qhwhiteboardman.capture.framework.gles.core.GlUtil;
import com.chen.qhwhiteboardman.capture.framework.gles.core.Program;

import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;

public class WhiteBoardProgram extends Program {
    private static final String CAMERA_INPUT_VERTEX_SHADER =
                    "attribute vec4 position;\n" +
                    "attribute vec4 texcoord;\n" +
                    "varying vec2 v_texcoord;\n" +
                    "void main() {\n" +
                    "    gl_Position = position;\n" +
                    "    v_texcoord = texcoord.xy;\n" +
                    "}\n";

    // Simple fragment shader for use with "normal" 2D textures.
    private static final String FRAGMENT_SHADER_2D =
                    "precision mediump float;\n" +
                    "varying vec2 v_texcoord;\n" +
                    "uniform sampler2D inputImageTexture;\n" +
                    "void main() {\n" +
                    "    gl_FragColor = vec4(texture2D(inputImageTexture, v_texcoord).rgb, 1);\n" +
                    "}\n";

    private static final float FULL_RECTANGLE_COORDS[] = {
            -1.0f, -1.0f,   // 0 bottom left
            1.0f, -1.0f,   // 1 bottom right
            -1.0f,  1.0f,   // 2 top left
            1.0f,  1.0f,   // 3 top right
    };
    private static final float FULL_RECTANGLE_TEX_COORDS[] = {
            0.0f, 1.0f,     //0 bottom left     //0.0f, 0.0f, // 0 bottom left
            1.0f, 1.0f,     //1 bottom right    //1.0f, 0.0f, // 1 bottom right
            0.0f, 0.0f,     //2 top left        //0.0f, 1.0f, // 2 top left
            1.0f, 0.0f,     //3 top right       //1.0f, 1.0f, // 3 top right
    };

    private final static String POSITION_COORDINATE = "position";
    private final static String TEXTURE_COORDINATE = "texcoord";
    private final static String TEXTURE_UNIFORM = "inputImageTexture";

    private int mVertexCoordLocation;
    private int mTexCoordLocation;
    private int mTexSampleLocation;

//    private FloatBuffer mVertexBuffer;
    private FloatBuffer mVertexBuffer2;
    private FloatBuffer mTextureBuffer;
    private FloatBuffer mTextureBuffer2;

    private int[] mFramebuffer = new int[1];
    private int[] mTargetTexture = new int[2];

    private int mWidth;
    private int mHeight;

    private int wbTextureId;

    private Context context;

    public void destroyProgram() {
        deleteFramebuffer();
        release();
    }

    public WhiteBoardProgram(Context context) {
        super(CAMERA_INPUT_VERTEX_SHADER, FRAGMENT_SHADER_2D);
//        mVertexBuffer = getDrawable2d().vertexArray();
        mTextureBuffer = getDrawable2d().texCoordArray();
        mVertexBuffer2 = GlUtil.createFloatBuffer(FULL_RECTANGLE_COORDS);
        mTextureBuffer2 = GlUtil.createFloatBuffer(FULL_RECTANGLE_TEX_COORDS);
        this.context = context;
    }

    public void update(int textureWidth, int textureHeight) {
        if (mWidth != textureWidth || mHeight != textureHeight) {
            mWidth = textureWidth;
            mHeight = textureHeight;
            deleteFramebuffer();
            bindFramebuffer(mWidth, mHeight);
            genImgTexture();
        } else if (wbTextureId == 0){
            genImgTexture();
        }
    }

    private void deleteFramebuffer() {
        if (mTargetTexture[0] != 0) {
            GLES20.glDeleteTextures(1, mTargetTexture, 0);
            mTargetTexture[0] = 0;
        }

        if (mFramebuffer[0] != 0) {
            GLES20.glDeleteFramebuffers(1, mFramebuffer, 0);
            mFramebuffer[0] = 0;
        }
    }

    private void bindFramebuffer(int width, int height) {
        GLES20.glGenFramebuffers(1, mFramebuffer, 0);
        GlUtil.checkGlError("glGenFramebuffers");

        GLES20.glGenTextures(2, mTargetTexture, 0);
        GlUtil.checkGlError("glGenTextures");

        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, mTargetTexture[0]);
        GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, 0, GLES20.GL_RGBA, width, height, 0,
                GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, null);

        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
                GLES20.GL_TEXTURE_MAG_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
                GLES20.GL_TEXTURE_MIN_FILTER, GLES20.GL_LINEAR);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
                GLES20.GL_TEXTURE_WRAP_S, GLES20.GL_CLAMP_TO_EDGE);
        GLES20.glTexParameterf(GLES20.GL_TEXTURE_2D,
                GLES20.GL_TEXTURE_WRAP_T, GLES20.GL_CLAMP_TO_EDGE);

        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFramebuffer[0]);
        GLES20.glFramebufferTexture2D(GLES20.GL_FRAMEBUFFER,
                GLES20.GL_COLOR_ATTACHMENT0,
                GLES20.GL_TEXTURE_2D,
                mTargetTexture[0], 0);

        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);
        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
    }

    private void genImgTexture() {
        final BitmapFactory.Options options = new BitmapFactory.Options();
        options.inScaled = false;

        // Read in the resource
        final Bitmap bitmap = BitmapFactory.decodeResource(
                context.getResources(), R.drawable.wb_img, options);
        wbTextureId = GlUtil.createImageTexture(bitmap);
    }

    @Override
    protected Drawable2d getDrawable2d() {
        return new Drawable2dFull();
    }

    @Override
    protected void getLocations() {
        mVertexCoordLocation = GLES20.glGetAttribLocation(mProgramHandle, POSITION_COORDINATE);
        GlUtil.checkGlError("glGetAttribLocation:" + mVertexCoordLocation);

        mTexCoordLocation = GLES20.glGetAttribLocation(mProgramHandle, TEXTURE_COORDINATE);
        GlUtil.checkGlError("glGetAttribLocation:" + mTexCoordLocation);

        mTexSampleLocation = GLES20.glGetUniformLocation(mProgramHandle, TEXTURE_UNIFORM);
        GlUtil.checkGlError("glGetUniformLocation:" + mTexSampleLocation);
    }

    @Override
    public void drawFrame(int textureId, float[] texMatrix, float[] mvpMatrix) {

    }

    public int process(int textureId) {

        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
        GLES20.glClearColor(0f, 0f, 0f, 0f);
        GLES20.glEnable(GL10.GL_DITHER);
        GLES20.glEnable(GL10.GL_DEPTH_TEST); //深度缓冲测试
        GLES20.glEnable(GLES20.GL_BLEND); //打开混合功能
        GLES20.glBlendFunc(GLES20.GL_ONE, GLES20.GL_ONE_MINUS_SRC_ALPHA); //指定混合模式

        GlUtil.checkGlError("drawMarkFrame");
        GLES20.glUseProgram(mProgramHandle);
        GlUtil.checkGlError("glUseProgram");

        // 如果数据是一样的，共用即可
        mVertexBuffer2.position(0);
        GLES20.glVertexAttribPointer(mVertexCoordLocation, 2, GLES20.GL_FLOAT, false, 0, mVertexBuffer2);
        GLES20.glEnableVertexAttribArray(mVertexCoordLocation);
        GlUtil.checkGlError("glEnableVertexAttribArray");
//        GLES20.glDisableVertexAttribArray(mVertexCoordLocation);

        //---先绘制白板

        mTextureBuffer2.position(0);
        GLES20.glVertexAttribPointer(mTexCoordLocation, 2, GLES20.GL_FLOAT, false, 0, mTextureBuffer2);
        GLES20.glEnableVertexAttribArray(mTexCoordLocation);
        GlUtil.checkGlError("glEnableVertexAttribArray");

        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, wbTextureId);
        GLES20.glUniform1i(mTexSampleLocation, 0);
        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFramebuffer[0]);

        GLES20.glViewport(0, 0, mWidth, mHeight);

        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);

        GLES20.glDisableVertexAttribArray(mTexCoordLocation);
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);

        //---再绘制摄像头

        mTextureBuffer.position(0);
        GLES20.glVertexAttribPointer(mTexCoordLocation, 2, GLES20.GL_FLOAT, false, 0, mTextureBuffer);
        GLES20.glEnableVertexAttribArray(mTexCoordLocation);
        GlUtil.checkGlError("glEnableVertexAttribArray");

        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureId);
        GLES20.glUniform1i(mTexSampleLocation, 0);

        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, mFramebuffer[0]);
        GlUtil.checkGlError("glBindFramebuffer");
        GLES20.glViewport(mWidth/4, 0, mWidth/4, mHeight/4);
        GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, 4);

        GLES20.glDisableVertexAttribArray(mVertexCoordLocation);
        GLES20.glDisableVertexAttribArray(mTexCoordLocation);
        GLES20.glActiveTexture(GLES20.GL_TEXTURE0);
        GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, 0);

        GLES20.glBindFramebuffer(GLES20.GL_FRAMEBUFFER, 0);
        GLES20.glUseProgram(0);

        return mTargetTexture[0];
    }
}
